#version 310 es
out highp vec4 Color;


in highp vec3 f_Coord;
in lowp vec2 f_TexCoord;
in lowp vec3 f_Normal;


uniform struct SpotLight
{
	lowp float power;
	lowp float cutoff;
	lowp vec3 ambient;
	lowp vec3 diffuse;
	lowp vec3 specular;
	lowp vec3 position;
	lowp vec3 direction;
} spotlights[4];
uniform struct OmniLight
{
	lowp float power;
	lowp vec3 ambient;
	lowp vec3 diffuse;
	lowp vec3 specular;
	lowp vec3 position;
	lowp vec3 direction;
} omnilights[4];

uniform lowp vec3 viewPos;
uniform sampler2D diffTex;
uniform sampler2D specTex;



highp vec3 pointLight(lowp int i, inout highp vec3 diffuse_texel, inout highp vec3 specular_texel)
{
	lowp float dist = length(omnilights[i].position - f_Coord);

	highp vec3 rayDir = normalize(omnilights[i].position - f_Coord);
	highp float rayCos = max(dot(f_Normal, rayDir), 0.);
	highp vec3 diffuse = rayCos * omnilights[i].diffuse * diffuse_texel;

	highp vec3 viewDir = normalize(viewPos - f_Coord);
	highp vec3 reflectDir = reflect(-rayDir, f_Normal);

	highp float viewCos = pow(max(dot(reflectDir, viewDir), 0.), 128. * specular_texel.r);
	highp vec3 specular = viewCos * omnilights[i].specular * specular_texel;

	return (diffuse + specular) * omnilights[i].power / dist;
}


highp vec3 spotLight(lowp int i, inout highp vec3 diffuse_texel, inout highp vec3 specular_texel)
{
	lowp float dist = length(spotlights[i].position - f_Coord);

	highp vec3 rayDir = normalize(spotlights[i].position - f_Coord);
	highp float rayCos = max(dot(f_Normal, rayDir), 0.);
	highp vec3 diffuse = rayCos * spotlights[i].diffuse * diffuse_texel;

	highp vec3 viewDir = normalize(viewPos - f_Coord);
	highp vec3 reflectDir = reflect(-rayDir, f_Normal);

	highp float viewCos = pow(max(dot(reflectDir, viewDir), 0.), 128. * specular_texel.r);
	highp vec3 specular = viewCos * spotlights[i].specular * specular_texel;

	highp float theta = dot(rayDir, -spotlights[i].direction);
	if (theta > spotlights[i].cutoff)
	{
		return (diffuse + specular) * spotlights[i].power / dist;
	}
	return spotlights[i].ambient * diffuse_texel / dist;
}

void main()
{
	const lowp int num_lights = 4;

	highp vec3 color = vec3(0.);
	highp vec3 diffuse_texel  = texture(diffTex, f_TexCoord).rgb;
	highp vec3 specular_texel = texture(specTex, f_TexCoord).rgb;

	for (lowp int i = 0; i < num_lights; i++)
	{
		color += pointLight(i, diffuse_texel, specular_texel);
		color += spotLight(i, diffuse_texel, specular_texel);
	}

	Color = vec4(color, 1.);
}